package com.ttx.uid.config;

import com.baidu.fsg.uid.impl.CachedUidGenerator;
import com.baidu.fsg.uid.worker.DisposableWorkerIdAssigner;
import com.baidu.fsg.uid.worker.MarkWorkerIdAssignerWrapper;
import com.baidu.fsg.uid.worker.WorkerIdAssigner;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 参照 test/resources/uid/cached-uid-spring.xml
 * @author TimFruit
 * @date 20-4-8 下午12:49
 */
@Configuration
public class UidDefaultGeneratorConfig {

    /*
    <!-- UID generator -->
	<bean id="disposableWorkerIdAssigner" class="com.baidu.fsg.uid.worker.DisposableWorkerIdAssigner" />

	<bean id="cachedUidGenerator" class="com.baidu.fsg.uid.impl.CachedUidGenerator">
		<property name="workerIdAssigner" ref="disposableWorkerIdAssigner" />

		<!-- 以下为可选配置, 如未指定将采用默认值 -->
		<!-- RingBuffer size扩容参数, 可提高UID生成的吞吐量. -->
		<!-- 默认:3， 原bufferSize=8192, 扩容后bufferSize= 8192 << 3 = 65536 -->
		<!--<property name="boostPower" value="3"></property>-->

		<!-- 指定何时向RingBuffer中填充UID, 取值为百分比(0, 100), 默认为50 -->
		<!-- 举例: bufferSize=1024, paddingFactor=50 -> threshold=1024 * 50 / 100 = 512. -->
		<!-- 当环上可用UID数量 < 512时, 将自动对RingBuffer进行填充补全 -->
		<!--<property name="paddingFactor" value="50"></property>-->

		<!-- 另外一种RingBuffer填充时机, 在Schedule线程中, 周期性检查填充 -->
		<!-- 默认:不配置此项, 即不实用Schedule线程. 如需使用, 请指定Schedule线程时间间隔, 单位:秒 -->
		<!--<property name="scheduleInterval" value="60"></property>-->

		<!-- 拒绝策略: 当环已满, 无法继续填充时 -->
		<!-- 默认无需指定, 将丢弃Put操作, 仅日志记录. 如有特殊需求, 请实现RejectedPutBufferHandler接口(支持Lambda表达式) -->
		<!--<property name="rejectedPutBufferHandler" ref="XxxxYourPutRejectPolicy"></property>-->

		<!-- 拒绝策略: 当环已空, 无法继续获取时 -->
		<!-- 默认无需指定, 将记录日志, 并抛出UidGenerateException异常. 如有特殊需求, 请实现RejectedTakeBufferHandler接口(支持Lambda表达式) -->
		<!--<property name="rejectedTakeBufferHandler" ref="XxxxYourTakeRejectPolicy"></property>-->

	</bean>
     */


    @Bean("disposableWorkerIdAssigner")
    public DisposableWorkerIdAssigner createDisposableWorkerIdAssigner(){
        DisposableWorkerIdAssigner assigner=new DisposableWorkerIdAssigner();
        return assigner;
    }





    //可复用workerId,保存到本机上
    @Bean("markWorkerIdAssigner")
    public WorkerIdAssigner createMarkWorkerIdAssigner(
            @Qualifier("disposableWorkerIdAssigner") WorkerIdAssigner assigner){
        MarkWorkerIdAssignerWrapper wrapper=new MarkWorkerIdAssignerWrapper(assigner);
        return wrapper;
    }



    @Bean("cachedUidGenerator")
    public CachedUidGenerator createCachedUidGenerator(
            @Qualifier("markWorkerIdAssigner") WorkerIdAssigner assigner){
        CachedUidGenerator uidGenerator=new CachedUidGenerator();
        uidGenerator.setWorkerIdAssigner(assigner);

        //总共64位，除去第一位，有效的为63位
        /*
        Snowflake算法描述：指定机器 & 同一时刻 & 某一并发序列，是唯一的。据此可生成一个64 bits的唯一ID（long）。默认采用上图字节分配方式：

        * sign(1bit)
          固定1bit符号标识，即生成的UID为正数。

        * delta seconds (28 bits)
          当前时间，相对于时间基点"2016-05-20"的增量值，单位：秒，最多可支持约8.7年

        * worker id (22 bits)
          机器id，最多可支持约420w次机器启动。内置实现为在启动时由数据库分配，默认分配策略为用后即弃，后续可提供复用策略。

        * sequence (13 bits)
          每秒下的并发序列，13 bits可支持每秒8192个并发。
         */
        uidGenerator.setEpochStr("2020-01-01"); //起始时间
        uidGenerator.setTimeBits(31); // 约可支持69.6年, 一旦投入生产，时间将不可更改，不然会重复， 利用时间的递增性，达到单个机器id的不重复
        uidGenerator.setWorkerBits(17); // 机器id  13w次 由于使用了markWorkerId，可以调小一点   以下两个参数可以改
        uidGenerator.setSeqBits(15); //  可支持每秒32768 个并发

        return uidGenerator;
    }

}
